home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_06_07
/
v6n7019a.txt
< prev
next >
Wrap
Text File
|
1989-09-26
|
14KB
|
486 lines
/* floppydr - floppy "doctor" program: low-low-level access to FDC */
#include <conio.h>
#include <dos.h>
#include <bios.h>
#include <stdio.h>
#include <ctype.h>
#define UBYTE unsigned char
#define flop_cmd(dr, motflag, moton, c, r, n, b) \
{ drive_sel(dr, motflag, moton); \
fdc_cmd(c, r, n, b); \
results(c[0], r);}
#define out_dor(cmd) outp(0x3F2, cmd)
#define in_stat() (inp(0x03f4))
#define out_dat(d) outp(0x3f5,d)
#define in_dat() (inp(0x3f5))
/* notes for Turbo-C: use outportb() and inportb() */
UBYTE buffer[1024];
char get_menu_choice();
UBYTE peekbyte(unsigned, unsigned);
long start_tmo(void);
#define READ_DATA 6
#define READ_DELETED_DATA 0xC
#define WRITE_DATA 5
#define WRITE_DELETED_DATA 9
#define READ_TRACK 2
#define READ_ID 0xA
#define FORMAT_TRACK 0xD
#define RECALIBRATE 7
#define SENSE_INTR_STATUS 8
#define SPECIFY 3
#define SENSE_DRIVE_STATUS 4
#define SEEK 0xF
typedef struct {
unsigned int ncmd;
unsigned int nres;
char ctype; /* N, I, R, or W,
for "no DMA", "Interrupt", "Read", "Write") */
} CMD_INFO;
CMD_INFO cmdt[16] = {
{0, 0, ' '}, /* 0x00 */
{0, 0, ' '}, /* 0x01 */
{9, 7, 'R'}, /* 0x02 read track */
{3, 0, 'N'}, /* 0x03 specify */
{2, 1, 'N'}, /* 0x04 sense drive status */
{9, 7, 'W'}, /* 0x05 write data */
{9, 7, 'R'}, /* 0x06 read data */
{2, 0, 'I'}, /* 0x07 recalibrate */
{1, 2, 'N'}, /* 0x08 sense interrupt status */
{9, 7, 'W'}, /* 0x09 write deleted data */
{2, 7, 'N'}, /* 0x0a read id */
{0, 0, ' '}, /* 0x0b */
{9, 7, 'R'}, /* 0x0c read deleted data */
{6, 7, 'W'}, /* 0x0d format track */
{0, 0, ' '}, /* 0x0e */
{3, 0, 'I'}, /* 0x0f seek */
};
#define NDPARM 12
struct DPARM {
UBYTE spec1; /* 0 specify byte 1 */
UBYTE spec2; /* 1 specify byte 2 */
UBYTE mot_off_wt; /* 2 meaningless */
UBYTE nrec; /* 3 number of bytes code */
UBYTE eot; /* 4 end-of-track */
UBYTE gpl; /* 5 gap length */
UBYTE dtl; /* 6 data length (if N = 0) */
UBYTE fgpl; /* 7 gpl for format */
UBYTE fd; /* 8 fill byte for format */
UBYTE hdsttl; /* 9 head settle time (milliseconds) */
UBYTE mot_start; /* 10 motor start time (1/8 seconds) */
UBYTE mt_mfm_sk; /* 11 bits: 0x80 = MT, 0x40 = MFM,
0x20 = SK */
} dparm = {0xcf, 0x02, 0x25, 0x02, 0x12, 0x2A,
0xFF, 0x50, 0xF6, 0x01, 0x04, 0xE0};
static char *dparmmsg[] = {
"0 - specify byte 1 (bits 0-3 = HUT, 4-7 = SRT) ",
"1 - specify byte 2 (bit 1-7 = HLT, 0 = 'no dma')",
"2 - meaningless (was motor start time)",
"3 - N: number of bytes code (2=512)",
"4 - EOT: end-of-track",
"5 - GPL: gap length",
"6 - DTL:data length (if N = 0)",
"7 - gpl for format",
"8 - fill byte for format",
"9 - head settle time (milliseconds) (not used)",
"10 - motor start time (1/8 seconds) (not used)",
"11 - bits: 0x80 = MT, 0x40 = MFM, 0x20 = SK"};
int main()
{
UBYTE unit = 0;
UBYTE track = 0;
UBYTE head = 0;
UBYTE sector = 1;
UBYTE nsector = 9;
UBYTE cd[9], rs[7], c, hdsds;
int nbyte, i, j;
printf("\n\nfloppy doctor program\n\n");
out_dor(0); /* reset card */
out_dor(0xC); /* select drive 0, allow ints & DMA */
while (1)
{
c = get_menu_choice();
switch (c)
{
case '0':
printf(" Enter Drive number:");
getnum("%d", &unit);
cd[0] = SENSE_DRIVE_STATUS;
cd[1] = (hdsds = unit + (head << 2));
flop_cmd(unit, 0, 0, cd, rs, 0, buffer);
break;
case '1':
cd[0] = SPECIFY;
cd[1] = dparm.spec1;
cd[2] = dparm.spec2;
flop_cmd(unit, 0, 0, cd, rs, 0, buffer);
break;
case '2':
cd[0] = RECALIBRATE;
cd[1] = unit;
flop_cmd(unit, 1, 200, cd, rs, 0, buffer);
break;
case '3':
printf(" Enter cylinder (track) number: ");
getnum("%d", &track);
cd[0] = SEEK;
cd[1] = hdsds;
cd[2] = track;
drive_sel();
flop_cmd(unit, 1, 200, cd, rs, 0, buffer);
break;
case '4':
printf(" Enter Head number:");
getnum("%d", &head);
hdsds = (hdsds & 0x3) | head;
break;
case '5':
cd[0] = READ_DATA + dparm.mt_mfm_sk;
goto read_write;
case '6':
cd[0] = WRITE_DATA + (dparm.mt_mfm_sk & 0xC0);
read_write:
printf(" Enter sector number: ");
getnum("%d", §or);
nbyte = 128 << dparm.nrec;
cd[1] = hdsds;
cd[2] = track;
cd[3] = head;
cd[4] = sector;
cd[5] = dparm.nrec;
cd[6] = dparm.eot;
cd[7] = dparm.gpl;
cd[8] = dparm.dtl;
flop_cmd(unit, 1, 200, cd, rs, nbyte, buffer);
if ((cd[0] & 0x0f) == READ_DATA) {
puts("");
dump_buf(nbyte, buffer);
}
break;
case '7':
for (i = 0; i < nsector; i++)
buffer[i * 4 + 2] = i;
cd[0] = FORMAT_TRACK + (dparm.mt_mfm_sk & 0x40);
cd[1] = hdsds;
cd[2] = dparm.nrec;
cd[3] = nsector;
cd[4] = dparm.fgpl; /* gap length for format */
cd[5] = dparm.fd; /* fill byte for format */
fdc_cmd(unit, 1, 200, cd, rs, nsector * 4, buffer);
break;
case '8':
printf("Enter number of times to read ids: ");
getnum("%d", &j);
drive_sel(unit, 1, 200);
cd[0] = READ_ID + (dparm.mt_mfm_sk & 0x40);
cd[1] = hdsds;
for (i = 0; i < j; i++) {
fdc_cmd(cd, rs, 0, buffer);
buffer[i * 4 + 0] = rs[3];
buffer[i * 4 + 1] = rs[4];
buffer[i * 4 + 2] = rs[5];
buffer[i * 4 + 3] = rs[6];
}
results(cd[0], rs); /* of the last command */
for (i = 0; i < j; i++)
printf("c = %d, h = %d, r = %d, n = %d\n",
buffer[i * 4 + 0], buffer[i * 4 + 1],
buffer[i * 4 + 2], buffer[i * 4 + 3]);
puts("Enter a key when ready");
getch();
puts("");
break;
case 'R':
dparm_rpt_chg();
break;
case 'X':
exit(0);
break;
default:
printf("\nIllegal command.\n");
}
}
}
char get_menu_choice()
{
char inp[80];
puts("");
puts("Menu:");
puts(" 0 - Drive #");
puts(" 1 - Specify (Step rate, Head unload, etc.)");
puts(" 2 - Recalibrate");
puts(" 3 - Seek (cylinder (track) number");
puts(" 4 - Head (surface)");
puts(" 5 - Read sector");
puts(" 6 - Write sector");
puts(" 7 - Format a track");
puts(" 8 - Read IDs");
puts(" R - Report and change the DPARM table");
puts(" X - Exit program");
puts("\n");
printf("Command: ");
gets(inp);
puts("");
return (isalpha(inp[0]) ? toupper(inp[0]) : inp[0]);
}
int dparm_rpt_chg()
{
int i, pi;
unsigned int nv;
UBYTE *a = &dparm.spec1;
for (i = 0; i < NDPARM; i++)
printf("(0x%02x) ", a[i]), puts(dparmmsg[i]);
puts("");
printf("Which to change (enter -1 if none to change): ");
getnum("%d", &pi);
if ((pi < 0) || (pi >= NDPARM))
return;
printf("dparm[%d] = %02x, new value: ", pi, a[pi]);
getnum("%x", &nv);
a[pi] = nv;
}
int fdc_cmd(UBYTE cmds[], UBYTE results[], int n